import ipaddress
from app.db.models.alert_groups import AlertGroup
from app.db.models.asset_tasks import AssetTasks
from app.db.models.jobs import Job
from app.errors import ParameterError
from app.libs.ip import check_source_ip
from app.libs.regexp import NAME_RE
from app.validators.asset import TargetUrl


def query_job_list(query, resp_fields, page=None, count=None, sort=None):
    data = Job.objects.find(query)
    total = data.count()  # 数据总量

    if sort:
        data = data.order_by(*sort)

    if resp_fields:
        data = data.only(*resp_fields)

    if page and count:
        if (page - 1) * count >= total:
            return [], total
        data = data.paginate(page, count)
        results = list(data.items.as_pymongo())
    else:
        results = [item.to_mongo().to_dict() for item in data]

    return results, total


def deal_job_info(job_list):
    results = []
    alert_group_ids = set()
    job_id_list = []
    for job in job_list:
        job_id_list.append(job.get("_id"))

        alert_group_id = ""
        if job.get("alertSettings", {}).get("alertGroupIds"):
            alert_group_id = job.get("alertSettings", {}).get("alertGroupIds")[0]
            alert_group_ids.add(alert_group_id)

        results.append({
            "target": job.get("targetUrl"),
            "target_name": job.get("note", ""),
            "target_ip": job.get("sourceIp", ""),
            "target_id": job.get("_id"),
            "enable_ping_monitor": False,  # 是否开启可用性ping周期任务检测
            "enable_http_monitor": False,  # 是否开启可用性http周期任务检测
            "enable_web_monitor": False,  # 是否开启web安全周期任务检测
            "enable_host_monitor": False,  # 是否开启主机监测周期任务检测
            "enable_alert": False,  # 是否开启任务结果告警  （待定，可能根据UI需求调整）
            "target_type": job.get("assetType", "web"),
            "alert_group_id": alert_group_id,
            "create_time": job.get("createTime", "")
        })

    # 获取告警策略
    alert_group_maps = dict()
    if alert_group_ids:
        alert_groups = AlertGroup.objects.filter(pk__in=list(alert_group_ids))
        alert_group_maps = {str(alert_group.pk): alert_group.enable for alert_group in alert_groups}

    # 获取周期性任务管理
    asset_tasks = AssetTasks.objects.filter(jobId__in=job_id_list, triggerType="schedule",
                                            taskGroupType__in=['host', 'web_security', 'http', 'ping'])
    asset_task_maps = {}
    for asset_task in asset_tasks:
        key = f"{str(asset_task.jobId)}{asset_task.taskGroupType}"
        if asset_task.enableMonitor:
            asset_task_maps[key] = asset_task.enableMonitor

    for item in results:
        job_id = str(item['target_id'])
        alert_group_id = item['alert_group_id']

        item["enable_ping_monitor"] = asset_task_maps.get(f"{job_id}ping", False)
        item["enable_http_monitor"] = asset_task_maps.get(f"{job_id}http", False)
        item["enable_web_monitor"] = asset_task_maps.get(f"{job_id}web_security", False)
        item["enable_host_monitor"] = asset_task_maps.get(f"{job_id}host", False)
        item["enable_alert"] = alert_group_maps.get(alert_group_id, False)

    return results


def check_add_asset_params(params):
    note = str(params.get("target_name", "")).strip()
    target_url = str(params.get("target", "")).strip()
    source_ip = params.get("target_ip", "")
    target_type = params.get("target_type", "")

    params = {"note": note, "target_url": "", "source_ip": source_ip, "target_type": target_type}

    if target_type not in ('web', 'host'):
        return False, "资产类型不合法"

    if not note:
        return False, "资产名称不能为空"

    if not NAME_RE.fullmatch(note):
        return False, "名称格式错误，只能输入1～50个中文、英文字母、数字、下划线"

    if not target_url:
        return False, "资产地址不能为空"

    if target_type == "web":
        try:
            web_target_url = TargetUrl(url=target_url)
            params["target_url"] = web_target_url.url
        except ParameterError:
            return False, "不能为私有地址"
        except Exception:
            return False, "资产地址格式错误"
    else:
        try:
            ip_obj = ipaddress.ip_address(target_url)
        except ValueError:
            return False, "主机资产地址应该是一个非私有段的IPv4"
        if ip_obj.version != 4 or ip_obj.is_private:
            return False, "主机资产地址应该是一个非私有段的IPv4"
        params["target_url"] = target_url

    if source_ip:
        status, message = check_source_ip(source_ip)
        if not status:
            return status, message
    if target_type == "host" and source_ip and (source_ip != target_url):
        return False, "主机资产地址和IP应该相同"

    return True, params


def change_job_schedule_task_monitor(uid, job_id, enable_monitor, target_group_types):
    AssetTasks.objects(uid=uid, pk=job_id, triggerType="schedule").update(enableMonitor=enable_monitor,
                                                                          taskGroupType__in=target_group_types)
